import 'dart:async';

import 'package:dio/dio.dart';
//import 'package:dio_flutter_transformer/dio_flutter_transformer.dart';
import 'package:connectivity/connectivity.dart';
import 'package:bot_toast/bot_toast.dart';

import '../config/app_const.dart';
import '../config/app_uri.dart';
import 'app_session.dart';
import 'app_popup.dart';
import '../config/_app_text.dart';

class AppRequest {
  late Dio dioHttp;
  CancelFunc? cancelLoading;

  AppRequest() {
    dioHttp = Dio();
    // dioHttp.transformer = Transformer();
    dioHttp.options.connectTimeout = AppConst.connectTimeout; //5s
    dioHttp.options.receiveTimeout = AppConst.receiveTimeout;
    dioHttp.options.headers = {
      'PD-UDID': AppSession.udid,
      'PD-VERSION': AppSession.packageInfo.version,
      // 'PD-REGION' : AppSession.region ?? '',
    };
    dioHttp.options.validateStatus = (int? status) {
      return (status??0) > 0;
    };

    dioHttp.interceptors.add(LogInterceptor(request: true, responseBody: true)); //Log
    dioHttp.interceptors.add(ConnectivityInterceptor()); //Connectivity Check
  }

  Future apiCall(
    String iv_method,
    String iv_path,
    Map<String, dynamic> im_headers,
    Map<String, dynamic> im_params,
    bool iv_loading,
  ) async {
    Response? lcResponse;

    Map<String, dynamic> em_resData = new Map();

    try {
      if (iv_loading) cancelLoading = BotToast.showLoading();

      if (im_headers.isNotEmpty) dioHttp.options.headers.addAll(im_headers);

      var lv_method = iv_method.toLowerCase();
      switch (lv_method) {
        case ApiConst.httpPost:
          lcResponse = await dioHttp.post(iv_path, data: im_params);
          break;
        case ApiConst.httpGet:
          lcResponse = await dioHttp.get(iv_path, queryParameters: im_params);
          break;
        default:
      }

      switch (lcResponse?.statusCode) {
        case 401:
          // AppSession.setAuthorToken('');
          em_resData['error'] = 11;
          em_resData['data'] = lcResponse?.data;
          em_resData['message'] = lcResponse?.data['ev_message'] ?? 'Error';
          break;
        case 200:
          if (lcResponse?.data['ev_error'] == 0) {
            em_resData['error'] = 0;
            em_resData['data'] = lcResponse?.data;
          } else {
            em_resData['error'] = 1;
            em_resData['data'] = lcResponse?.data;
            em_resData['message'] = '出错了';
            if (lcResponse?.data['ev_message'] ==
                'SYSTEM_ERROR_W_MSG') if ((lcResponse?.data['ev_context'] ?? '').isNotEmpty)
              em_resData['message'] = lcResponse?.data['ev_context'];
            // em_resData['message'] = lc_response.data['ev_message'] ?? 'Error';
          }
          break;
        case 901:
          em_resData['error'] = 14;
          em_resData['message'] = 'Error';

          break;

        default:
          if (lcResponse?.data['ev_error'] == 1) {
            em_resData['error'] = 12;
            em_resData['data'] = lcResponse?.data;
            em_resData['message'] = '出错了';
            if (lcResponse?.data['ev_message'] ==
                'SYSTEM_ERROR_W_MSG') if ((lcResponse?.data['ev_context'] ?? '').isNotEmpty)
              em_resData['message'] = lcResponse?.data['ev_context'];
          } else
            throw 'Request Error';
          break;
      }

      if (iv_loading) cancelLoading!();
    } catch (e) {
      print(e);
      em_resData['error'] = 13;
      // em_resData['message'] = AppSession.i18n.l_util_request__system_error;
      if (iv_loading) {
        cancelLoading!();
        // BotToast.showText(text: AppSession.i18n.l_util_request__unknown_error);
      }
    }
    // if (em_resData['error'] == 11) AppPopupService.showText("Authorization Issue");
    if (em_resData['error'] == 12) AppPopupService.showText("Network Issue");
    if (em_resData['error'] == 13) AppPopupService.showText("Unknown Issue");
    if (em_resData['error'] == 14) AppPopupService.showText("Network  Issue");
    return em_resData;
  }

  Future futureWrapper(
    String iv_req_method,
    String iv_uri,
    Map<String, dynamic> im_header,
    Map<String, dynamic> im_param,
    bool iv_token,
    bool iv_loading,
  ) async {
    AppRequest lv_req = new AppRequest();
    Map<String, dynamic> lm_header = {};
    Map<String, dynamic> lm_param = {};
    Map<String, dynamic> em_result = {};

    if (iv_token) {
      var lv_token = await AppSession.refreshToken();

      lm_header.addAll({'PD-AUTHTOKEN': lv_token ?? ''}); //AppSession.authortoken
      // lm_header.addAll({'PD-AUTHTOKEN': '1234'});
    }
    if ((AppSession.pushid ?? '').isNotEmpty) {
      lm_header.addAll({'PD-PUSHID': AppSession.pushid ?? ''});
    }

    lm_header.addAll(im_header);
    lm_param.addAll(im_param);

    var lm_response = await lv_req.apiCall(
      iv_req_method,
      iv_uri,
      lm_header,
      lm_param,
      iv_loading,
    );

    if (lm_response['error'] == 0) {
      em_result = lm_response['data'];
    } else if (lm_response['error'] != 11) {
      AppPopupService.showText(((lm_response['message'] ?? '').isNotEmpty)
          ? lm_response['message']
          : AppText.text['util_req_error']);
    }
    print(lm_response['error']);
    return em_result;
  }
}

class ConnectivityInterceptor extends InterceptorsWrapper {

  @override
  onRequest(RequestOptions options,RequestInterceptorHandler handler) async {
    //没有网络
    var connectivityResult = await (new Connectivity().checkConnectivity());
    if (connectivityResult == ConnectivityResult.none) {
      return handler.resolve(new Response(requestOptions: options,statusCode: 901));
    }
    return handler.next(options);
  }

}
